`include "defines.svh"
`include "axi_defines.svh"
`default_nettype wire

module axi_ls(
    input clk,
    input reset,

    input data_sram_en,
    input word_t debug_data_pc,
    input data_sram_wen,
    input word_t data_sram_addr,
    input logic[3:0] data_sram_mask,
    output word_t data_sram_rdata,
    input word_t data_sram_wdata, 
    
    output logic  axi_data_flushreq,
    output word_t debug_pc,
    
    //R
    output logic  arvalid,
    output word_t araddr,
    input  logic  arready,

    output logic  rready,
    input  word_t rdata,
    input  ysyx_resp_t rresp,
    input  logic  rvalid,

    // W
    output logic  awvalid,
    output word_t awaddr,
    input  logic  awready,

    output logic  wvalid,
    output  word_t wdata,
    output  ysyx_strb_t wstrb,
    input  logic  wready,

    output logic  bready,
    input  ysyx_resp_t bresp,
    input  logic  bvalid,

    // extra signals
    input axi_master_read_in_t extra_rin,
    output axi_master_read_out_t extra_rout,
    input axi_master_write_in_t extra_win,
    output axi_master_write_out_t extra_wout
);

    // TODO:暂时不使用AXI4Full的扩展信号


    // signal
    rstate_t rstate;
    logic ar_shake,r_shake,aw_shake,w_shake,b_shake;
    
    assign ar_shake = arready && arvalid;
    assign r_shake = rready && rvalid;
    assign aw_shake = awready & awvalid;
    assign w_shake = wready & wvalid;
    assign b_shake = bready & bvalid;
    // R
    always_ff @(posedge clk) begin
        if (reset) begin
            rstate <= S_IDLE;
        end else if(rstate == S_IDLE) begin
            if(data_sram_en && ~data_sram_wen) begin
                araddr <= data_sram_addr;
                debug_pc <= debug_data_pc;
                arvalid <= `ON;
                extra_rout <= `NULL;
                rstate  <= AR_WAIT;
            end
        end else if(rstate == AR_WAIT) begin
            if(ar_shake) begin
                rstate <= R_RECV;
                rready <= `ON;
                arvalid <= `OFF;
            end
        end else if(rstate == R_RECV) begin
            if(r_shake) begin
                rready <= `OFF;
                rstate <= S_IDLE;
            end
        end
    end

    assign data_sram_rdata = rdata;

    // W
    wstate_t wstate;
    always_ff @(posedge clk) begin
        if(reset) begin
            wstate <= S_IDLE_;
        end else if(wstate == S_IDLE_) begin
            if(data_sram_wen) begin
                awvalid <= `ON;
                wvalid  <= `ON;
                awaddr  <= data_sram_addr;
                wdata   <= data_sram_wdata;
                wstrb   <= data_sram_mask;
                debug_pc <= debug_data_pc;
                wstate  <= AW_WAIT;
                extra_wout <= `NULL;
            end
        end else if(wstate == AW_WAIT) begin
            if(aw_shake && w_shake) begin
                awvalid <= `OFF;
                wvalid  <= `OFF;
                bready  <= `ON;
                wstate  <= W_RECV;
            end
        end else if(wstate == W_RECV) begin
            if(b_shake) begin
                bready <= `OFF;
                wstate <= S_IDLE_;
            end
        end
    end


    ysyx_resp_t rresp_r,bresp_r;
    logic axi_data_flushreq_load,axi_data_flushreq_store;
    always_comb begin
        rresp_r = rresp;
        bresp_r = bresp;
        // if(rstate == S_IDLE && data_sram_en && ~data_sram_wen) begin
        //     axi_data_flushreq_load  = `ON;
        // end else if(rstate == AR_WAIT) begin
        //     axi_data_flushreq_load  = `ON;
        // end else if(rstate == R_RECV && r_shake) begin
        //     axi_data_flushreq_load  = `ON;
        // end else begin
        //     axi_data_flushreq_load  = `OFF;
        // end
        axi_data_flushreq_load = data_sram_en && ~data_sram_wen && ~(rstate != S_IDLE && r_shake);

        if(wstate == S_IDLE_ && data_sram_wen) begin
            axi_data_flushreq_store  = `ON;
        end else if(wstate == AW_WAIT) begin
            axi_data_flushreq_store  = `ON;
        end else if(wstate == W_RECV && w_shake && aw_shake) begin
            axi_data_flushreq_store  = `ON;
        end else begin
            axi_data_flushreq_store  = `OFF;
        end

        axi_data_flushreq = axi_data_flushreq_load | axi_data_flushreq_store;
    end
endmodule
